<template>
  <ElForm
    v-show="getShow"
    ref="loginFormRef"
    :model="loginData.loginForm"
    :rules="loginRules"
    class="login-form"
    label-position="top"
    label-width="120px"
    size="large"
  >
    <el-row class="mx-[-10px]">
      <el-col :span="24" class="px-10px">
        <el-form-item>
          <LoginFormTitle class="w-full" />
        </el-form-item>
      </el-col>
      <el-col :span="24" class="px-10px">
        <el-form-item prop="loginName">
          <el-input
            v-model="loginData.loginForm.loginName"
            :placeholder="t('login.usernamePlaceholder')"
            :prefix-icon="iconAvatar"
            autocomplete="off"
          />
        </el-form-item>
      </el-col>
      <el-col :sm="24" class="px-10px">
        <el-form-item prop="password">
          <el-input
            v-model="loginData.loginForm.password"
            :placeholder="t('login.passwordPlaceholder')"
            :prefix-icon="iconLock"
            type="password"
            :show-password="false"
            autocomplete="off"
            @keyup.enter="handleLogin"
          />
        </el-form-item>
      </el-col>
      <el-col :span="24" class="px-10px" v-if="loginData.captchaEnable">
        <el-form-item prop="captcha">
          <el-input
            v-model="loginData.loginForm.captcha"
            autocomplete="off"
            :placeholder="t('login.codePlaceholder')"
            :prefix-icon="iconCaptcha"
            maxlength="4"
            class="captcha-input"
            @focus="handleCaptchaFocus"
            @keyup.enter="handleLogin"
          >
            <template #append>
              <!--              <img-->
              <!--                alt=""-->
              <!--                :src="loginData.captchaUrl"-->
              <!--                @click="getCaptcha"-->
              <!--                class="h-39px -mt-1px cursor-pointer"-->
              <!--              />-->
              <el-image
                :src="loginData.captchaUrl"
                @click="getCaptcha"
                class="w-104px h-39px -mt-1px cursor-pointer"
              >
                <template #error>
                  <div class="px-6">点击刷新</div>
                </template>
              </el-image>
            </template>
          </el-input>
        </el-form-item>
      </el-col>
      <el-col :span="24" class="px-10px -my-20px">
        <el-form-item>
          <el-row justify="space-between" class="w-full">
            <el-col :span="6">
              <el-checkbox v-model="loginData.loginForm.rememberMe">
                {{ t('login.remember') }}
              </el-checkbox>
            </el-col>
            <el-col :span="18">
              <el-link
                class="float-right"
                type="primary"
                @click="setLoginState(LoginStateEnum.RESET_PASSWD)"
              >
                {{ t('login.forgetPassword') }}
              </el-link>
              <!-- max-width: 767.9px时隐藏 -->
              <el-link
                class="float-right mr-10px !lt-md:hidden"
                type="primary"
                @click="handleSocialLogin(SocialTypeEnum.Wechat_Enterprise.type)"
              >
                {{ t('login.qyWxQRCode') }}
              </el-link>
              <el-link
                class="float-right mr-10px !lt-md:hidden"
                type="primary"
                @click="setLoginState(LoginStateEnum.SMS_CODE_LOGIN)"
              >
                {{ t('login.btnMobile') }}
              </el-link>
            </el-col>
          </el-row>
        </el-form-item>
      </el-col>
      <el-col :span="24" class="px-10px">
        <el-form-item>
          <XButton
            :loading="loginLoading"
            :title="t('login.login')"
            class="w-full"
            type="primary"
            @click="handleLogin"
          />
        </el-form-item>
      </el-col>
      <!-- 默认隐藏，min-width: 768px时展示 -->
      <el-col :span="24" class="px-10px !hidden !lt-md:block">
        <el-form-item>
          <el-row :gutter="5" class="w-full">
            <el-col :span="12">
              <XButton
                :title="t('login.btnMobile')"
                class="w-full"
                @click="setLoginState(LoginStateEnum.SMS_CODE_LOGIN)"
              />
            </el-col>
            <el-col :span="12">
              <XButton
                :title="t('login.qyWxQRCode')"
                class="w-full"
                @click="handleSocialLogin(SocialTypeEnum.Wechat_Enterprise.type)"
              />
            </el-col>
            <!--            <el-col :span="8">-->
            <!--              <XButton :title="t('login.btnRegister')" class="w-full"/>-->
            <!--            </el-col>-->
          </el-row>
        </el-form-item>
      </el-col>
    </el-row>
  </ElForm>
</template>

<script setup lang="ts">
import * as authUtil from '@/utils/auth'
import * as LoginApi from '@/api/base/login'
import { LoginStateEnum, useLoginState } from './useLogin'
import LoginFormTitle from './LoginFormTitle.vue'
import type { RouteLocationNormalizedLoaded } from 'vue-router'
import { ElLoading } from 'element-plus'
import { SocialTypeEnum } from '@/utils/constants'

defineOptions({ name: 'PasswdLoginForm' })

const { t } = useI18n()
const iconAvatar = useIcon({ icon: 'ep:avatar' })
const iconLock = useIcon({ icon: 'ep:lock' })
const iconCaptcha = useIcon({ icon: 'hugeicons:security-validation' })
const loginFormRef = ref()
const { getLoginState, setLoginState } = useLoginState()
const { currentRoute, push } = useRouter()
// const currentRoute = useRoute()
const redirect = ref('')
const loginLoading = ref(false)

const getShow = computed(() => unref(getLoginState) == LoginStateEnum.PASSWD_LOGIN)

const loginRules = {
  loginName: [required], // @/utils/formRules中的required (build/vite/index中配置的auto-import)
  password: [required],
  captcha: [required]
}

const loginData = reactive({
  isShowPassword: false,
  captchaEnable: true,
  tenantEnable: import.meta.env.VITE_APP_TENANT_ENABLE === 'true',
  captchaUrl: '',
  loginForm: {
    loginName: import.meta.env.VITE_APP_DEFAULT_LOGIN_LOGINNAME || '',
    password: import.meta.env.VITE_APP_DEFAULT_LOGIN_PASSWORD || '',
    captcha: '',
    captchaId: '',
    rememberMe: false
  }
})

// 组件有时会被复用，此时created(onBeforeMount)、mounted(onMounted)生命周期钩子不会被执行，beforeRouteUpdate钩子会被触发(但第一次组件加载时不会触发该钩子)
// 所以这里需要使用侦听当前路由的方式，获取redirect参数的值
watch(
  () => currentRoute.value,
  (route: RouteLocationNormalizedLoaded) => {
    redirect.value = route?.query?.redirect as string
  },
  { immediate: true }
)

let loadingInstance: Closable
const handleLogin = async () => {
  loginLoading.value = true
  try {
    if (await formValidate(loginFormRef)) {
      return
    }
    const loginForm = { ...loginData.loginForm }
    const res = await LoginApi.passwdLogin(loginForm)
    if (!res) {
      return
    }
    loadingInstance = ElLoading.service({
      lock: true,
      text: `${t('common.systemLoading')}...`,
      background: 'rgba(0, 0, 0, 0.7)'
    })
    if (loginForm.rememberMe) {
      const { loginName, password, rememberMe } = loginForm
      authUtil.setLoginForm({ loginName, password, rememberMe })
    } else {
      authUtil.removeLoginForm()
    }
    authUtil.setToken(res)
    push({ path: redirect.value || '/' })
  } catch (e) {
    if (loginData.captchaEnable) {
      getCaptcha()
    }
  } finally {
    loginLoading.value = false
    loadingInstance?.close()
  }
}

let lastLoadCaptTime = new Date().getTime()
const getCaptcha = () => {
  // 刷新图形验证码
  lastLoadCaptTime = new Date().getTime()
  LoginApi.getCaptcha('staff_auth').then((res) => {
    loginData.captchaEnable = res.captchaEnabled ?? true
    if (loginData.captchaEnable) {
      loginData.captchaUrl = res.captchaBase64
      loginData.loginForm.captchaId = res.captchaId
    }
  })
}

const handleCaptchaFocus = () => {
  // 验证码聚焦时，若验证码已过期，则自动刷新
  if (new Date().getTime() - lastLoadCaptTime > 2 * 60 * 1000) {
    getCaptcha()
  }
}

const getLoginFormCache = () => {
  const loginForm = authUtil.getLoginForm()
  if (loginForm) {
    loginData.loginForm = {
      ...loginData.loginForm,
      loginName: loginForm.loginName ? loginForm.loginName : loginData.loginForm.loginName,
      password: loginForm.password ? loginForm.password : loginData.loginForm.password,
      rememberMe: loginForm.rememberMe
    }
  }
}

const handleSocialLogin = async (type: number) => {
  // 计算 redirectUri
  // tricky: type、redirect需要先encode一次，否则钉钉回调会丢失。
  // 配合 Login/SocialLogin.vue#getUrlValue() 使用
  const redirectUri =
    location.origin +
    '/social-login?' +
    encodeURIComponent(`type=${type}&redirect=${redirect.value || '/'}`)
  window.location.href = await LoginApi.socialAuthRedirect(type, redirectUri)
}

// 在组件实例化时被调用，此时数据已设置(data已返回，并已进行响应式处理)，事件监听器也已添加(实例化时绑定事件侦听器，如v-on绑定的事件处理器)，但模板尚未挂载
onBeforeMount(() => {
  getLoginFormCache()
  getCaptcha()
})
</script>

<style scoped lang="scss">
.captcha-input {
  :deep(.el-input-group__append) {
    padding-right: 0;
    padding-left: 0;
  }
}
</style>
